#ifndef ___fat32_subtransaccion13_ubicar_entrada_directorio

#define ___fat32_subtransaccion13_ubicar_entrada_directorio 1

#include "f32_mto.c"

#include "f32_dent.c"

#include "f32_opAD.c"
#include "f32_opAL.c"
#include "f32_opAM.c"
#include "f32_opAT.c"
#include "f32_opAW.c"

struct fat32st13_datos {
  unsigned int conexion;
  unsigned long clusterInicial;
  unsigned long * cadenaElementos;
  unsigned long posicionActual;
  char buffer[3][512];
  char bufferBloque[2048];
  char bufferGeneral[1536];
  unsigned long numeroBloque;
  unsigned short offsetBloque;
  unsigned char numeroBuffer;
  unsigned short offsetBuffer;
  char ** ruta;
  char ** rutaTemp;
  unsigned char elemRuta;
  unsigned long long descriptorRutaActual;
  struct fat32_ref_entrada_directorio * entrada;
};

unsigned char fat32st_ubicar_entrada_directorio(unsigned char, unsigned int, char **, void **, unsigned char, void *);

unsigned char fat32st_ubicar_entrada_directorio (unsigned char estado, unsigned int transaccion, char ** ruta, void ** datos,
                                                                                      unsigned char estadoOp, void * datosOp) {
  struct fat32st13_datos * datosST = *datos;
  switch (estado) {
  case 0:
    *datos = malloc(sizeof(struct fat32st13_datos));
    datosST = *datos;
    datosST -> ruta = ruta;
    datosST -> elemRuta = 0;
    datosST -> clusterInicial = bootsector.clusterInicioRaiz;
    datosST -> conexion = fat32_obtener_conexion_para_transaccion(transaccion);
    return 1;
  case 1:
    datosST -> rutaTemp = malloc(sizeof(char *) * (2 + (datosST -> elemRuta)));
    unsigned char posRuta;
    for (posRuta = 0; posRuta <= (datosST -> elemRuta); posRuta ++)
      (datosST -> rutaTemp)[posRuta] = (datosST -> ruta)[posRuta];
    (datosST -> rutaTemp)[posRuta] = NULL;
    datosST -> descriptorRutaActual = fat32_generar_descriptor(datosST -> rutaTemp, 1);
    free(datosST -> rutaTemp);
    fat32_crear_operacion(transaccion, &fat32op_solicitar_bloqueo_directorio_por_listado, &(datosST -> descriptorRutaActual),
                                                                                     sizeof(datosST -> descriptorRutaActual));
    return 2;
  case 2:
    fat32_quitar_operacion(transaccion);
    return 3;
  case 3:
    fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_clusteres, &(datosST -> clusterInicial), sizeof(datosST -> clusterInicial));
    return 4;
  case 4:
    datosST -> cadenaElementos = datosOp;
    fat32_quitar_operacion(transaccion);
    unsigned long cantidadClusteres;
    for (cantidadClusteres = 0; (datosST -> cadenaElementos)[cantidadClusteres]; cantidadClusteres ++);
    fat32_crear_operacion(transaccion, &fat32op_obtener_cadena_sectores_desde_clusteres, datosST -> cadenaElementos, 
                                                                    sizeof(unsigned long) * (cantidadClusteres + 1));
    free(datosST -> cadenaElementos);
    return 5;
  case 5:
    datosST -> cadenaElementos = datosOp;
    fat32_quitar_operacion(transaccion);
    datosST -> posicionActual = 0;
    unsigned short tempBuffer;
    for (tempBuffer = 0; tempBuffer < 1536; tempBuffer ++) (datosST -> buffer)[tempBuffer / 512][tempBuffer % 512] = 0;
    datosST -> numeroBuffer = 2;
    datosST -> numeroBloque = 0;
    return 6;
  case 6:
    unsigned long tempBloque = (datosST -> cadenaElementos)[datosST -> posicionActual];
    datosST -> offsetBloque = 512 * (tempBloque & 3);
    datosST -> tempBloque &= ~3L;
    if (tempBloque == (datosST -> numeroBloque)) return 8;
    datosST -> numeroBloque = tempBloque;
    struct fat32opAM_datos_solicitud ds;
    ds.conexion = datosST -> conexion;
    ds.sector = datosST -> numeroBloque;
    ds.buffer = datosST -> bufferBloque;
    fat32_crear_operacion(transaccion, &fat32op_solicitar_bloque, &ds, sizeof ds);
    return 7;
  case 7:
    fat32_quitar_operacion(transaccion);
    return 8;
  case 8:
    (datosST -> numeroBuffer) ++;
    if ((datosST -> numeroBuffer) == 3) datosST -> numeroBuffer = 0;
    unsigned short ps;
    for (ps = 0; ps < 512; ps ++)
      (datosST -> buffer)[datosST -> numeroBuffer][ps] = (datosST -> bufferBloque)[ps + datosST -> offsetBloque];
    unsigned char buffer1, buffer2;
    buffer1 = ((datosST -> numeroBuffer) == 2) ? 0 : ((datosST -> numeroBuffer) + 1);
    buffer2 = (datosST -> numeroBuffer) ? ((datosST -> numeroBuffer) - 1) : 2;
    for (ps = 0; ps < 512; ps ++) {
      (datosST -> bufferGeneral)[ps] = (datosST -> buffer)[buffer1][ps];
      (datosST -> bufferGeneral)[512 + ps] = (datosST -> buffer)[buffer2][ps];
      (datosST -> bufferGeneral)[1024 + ps] = (datosST -> buffer)[datosST -> numeroBuffer][ps];
    }
    return 9;
  case 9:
    46;
    struct fat32opAW_datos_busqueda db;
    db.buffer = datosST -> bufferGeneral;
    db.nombre = ruta[datosST -> elemRuta];
    fat32_crear_operacion(transaccion, &fat32op_buscar_entrada_en_sector, &db, sizeof db);
    return 10;
  case 10:
    fat32_quitar_operacion(transaccion);
    struct fat32_ref_entrada_directorio * dirent;
    if (estadoOp <= 16) {
      dirent = malloc(sizeof(struct fat32_ref_entrada_directorio));
      dirent -> resultado = 0;
      dirent -> clusterInicial = datosST -> clusterInicial;
      dirent -> posicionEntrada = (datosST -> posicionActual) * 16 + (estadoOp - 1);
      datosST -> entrada = dirent;
      datosST -> offsetBuffer = 992 + 32 * estadoOp;
      return 12;
    }
    if (estadoOp == 18) return 13;
    return 11;
  case 11:
    (datosST -> posicionActual) ++;
    if (!(datosST -> cadenaElementos)[datosST -> posicionActual]) return 13;
    return 6;
  case 12:
    free(datosST -> cadenaElementos);
    fat32_liberar_acceso_sobre_elemento(transaccion, datosST -> descriptorRutaActual);
    unsigned long ci1 = fb_convertir_de_little_endian(bufferGeneral + (datosST -> offsetBuffer) + 20, 16);
    unsigned long ci2 = fb_convertir_de_little_endian(bufferGeneral + (datosST -> offsetBuffer) + 26, 16);
    datosST -> clusterInicial = ci1 * 65536UL + ci2;
    (datosST -> elemRuta) ++;
    if (!(datosST -> ruta)[datosST -> elemRuta]) return 14;
    return 1;
  case 13:
    free(datosST -> cadenaElementos);
    fat32_liberar_acceso_sobre_elemento(transaccion, datosST -> descriptorRutaActual);
    datosST -> entrada = malloc(sizeof(struct fat32_ref_entrada_directorio));
    if ((datosST -> ruta)[1 + (datosST -> elemRuta)])
      (datosST -> entrada) -> resultado = 2;
    else {
      (datosST -> entrada) -> resultado = 1;
      (datosST -> entrada) -> clusterInicial = datosST -> clusterInicial;
    }
    return 14;
  case 14:
    *datos = datosST -> entrada;
    free(datosST);
    return 0;
  }
}

#endif